package com.senven.api.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.senven.api.annotation.LogInfo;
import com.senven.api.pojo.Account;
import com.senven.api.service.AccountService;
import com.senven.api.service.LogService;
import com.senven.api.utils.LogUtil;
import org.apache.ibatis.ognl.ObjectMethodAccessor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.logout.LogoutHandler;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;

/**
 * @author LQP
 * 安全配置类
 */

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private AccountService accountService;

    @Autowired
    private LogService logService;

    @Override
    protected void configure(HttpSecurity http) throws Exception
    {
        http.headers().frameOptions().sameOrigin();
        http.authorizeRequests()
                .antMatchers("/api/admin/**").hasAnyRole("admin","student")
                .antMatchers("/api/organ/**").hasAnyRole("student","admin")
                .antMatchers("/Student/**").hasRole("student")
                .antMatchers("/api/student/**").hasRole("student")
                .antMatchers("/layui/**").permitAll()
                .antMatchers("/WeAdmin/**").permitAll()
                .antMatchers("/Student/**").permitAll()
//                .anyRequest().permitAll()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .loginPage("/WeAdmin/login.html")
                .loginProcessingUrl("/login").permitAll()
                .usernameParameter("username")
                .passwordParameter("passwd")
                .successHandler(new AuthenticationSuccessHandler() {
                    @Override
                        public void onAuthenticationSuccess(HttpServletRequest Request, HttpServletResponse Response, Authentication authentication) throws IOException, ServletException {

                        //LogService logService = new LogService();
                        //logService.insertLogin();
                        //Response.setContentType("application/json;charset=utf-8");
                        HttpSession session = Request.getSession();
                        Account account = (Account) SecurityContextHolder.getContext()
                                .getAuthentication()
                                .getPrincipal();
                        System.out.println(account.getPassword());
                        session.setAttribute("account",account.getUsername());
                        //session.setAttribute("password",account.getPassword());
                        logService.insertLog(LogUtil.getLog("登录日志","登陆成功","操作成功",Request));
                        Object principal = authentication.getPrincipal();
                        if(account.getRoleid() == 1)
                            Response.sendRedirect("/WeAdmin/index.html");
                        else
                            Response.sendRedirect("/Student/navbar.html");
                        /*PrintWriter out = Response.getWriter();
                        Response.setStatus(200);
                        Map<String, Object> map = new HashMap<>();
                        ObjectMapper om = new ObjectMapper();
                        map.put("status", 200);
                        map.put("msg",principal);
                        out.write(om.writeValueAsString(map));
                        out.flush();
                        out.close();*/

                    }
                })
                .failureHandler(new AuthenticationFailureHandler() {
                    @Override
                    public void onAuthenticationFailure(HttpServletRequest Request, HttpServletResponse Response, AuthenticationException e) throws IOException, ServletException {
                        Response.setContentType("application/json;charset=utf-8");
                        PrintWriter out = Response.getWriter();
                        Response.setStatus(401);
                        Map<String, Object> map = new HashMap<>();
                        ObjectMapper om = new ObjectMapper();
                        map.put("status",401);
                        if(e instanceof BadCredentialsException){
                            map.put("msg","账号或密码错误");
                        }else{
                            map.put("msg","登陆失败");
                        }
                        out.write(om.writeValueAsString(map));
                        out.flush();
                        out.close();
                    }
                })
                .and()
                .logout()
                .logoutUrl("/logout")
                .clearAuthentication(true)
                .invalidateHttpSession(true)
                .addLogoutHandler(new LogoutHandler() {
                    @Override
                    public void logout(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) {

                    }
                })
                .logoutSuccessHandler(new LogoutSuccessHandler() {
                    @Override
                    public void onLogoutSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
                        httpServletResponse.sendRedirect("/login.html");
                    }
                })
                .permitAll()
                .and()
                .csrf().disable();
    }

    @Bean
    PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth)throws Exception{
        auth.userDetailsService(accountService);
    }

    /** 放行静态资源 */
    @Override
    public void configure(WebSecurity web) throws Exception {
        //解决静态资源被拦截的问题
        web.ignoring().antMatchers("/css/**");
        web.ignoring().antMatchers("/page/**");
        web.ignoring().antMatchers("/js/**");
        web.ignoring().antMatchers("/layui/**");
        web.ignoring().antMatchers("/images/**");
        web.ignoring().antMatchers("/WeAdmin/**");
    }


}
